package com.xiaoshuidi.cloud.module.contract.controller.admin.contract;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.excel.core.util.ExcelUtils;
import com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils;
import com.xiaoshuidi.cloud.framework.tenant.core.aop.TenantIgnore;
import com.xiaoshuidi.cloud.module.contract.controller.admin.bill.vo.SettlementOrderFeeVO;
import com.xiaoshuidi.cloud.module.contract.controller.admin.bill.vo.rentOrder.RentOrderCountVO;
import com.xiaoshuidi.cloud.module.contract.controller.admin.contract.vo.*;
import com.xiaoshuidi.cloud.module.contract.controller.admin.contract.vo.company.CompanyContractSonPageReqVO;
import com.xiaoshuidi.cloud.module.contract.controller.admin.contract.vo.company.CompanySonsContractListExcelVO;
import com.xiaoshuidi.cloud.module.contract.controller.admin.contract.vo.ownerContract.ChangeHousekeepReqVO;
import com.xiaoshuidi.cloud.module.contract.controller.admin.contract.vo.settlement.ContractSettementVO;
import com.xiaoshuidi.cloud.module.contract.convert.contract.ContractConvert;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.contract.ContractFixedFeeVo;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.contract.ContractRoomDO;
import com.xiaoshuidi.cloud.module.contract.enums.ApiConstants;
import com.xiaoshuidi.cloud.module.contract.service.contract.ContractFixedFeeService;
import com.xiaoshuidi.cloud.module.contract.service.contract.ContractRoomService;
import com.xiaoshuidi.cloud.module.contract.service.contract.ContractSettlementService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLDecoder;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import static com.xiaoshuidi.cloud.framework.common.pojo.CommonResult.success;

@Tag(name = "管理后台 - 租客合同")
@RestController
@RequestMapping(ApiConstants.NAME + "/contract")
@Validated
public class ContractRoomController {

    @Resource
    private ContractRoomService contractRoomService;

    @Resource
    private ContractSettlementService contractSettlementService;

    @Resource
    private ContractFixedFeeService contractFixedFeeService;

    @PostMapping("/create")
    @Operation(summary = "创建租客合同")
//    @PreAuthorize("@ss.hasPermission('contract:create')")
    public CommonResult<Void> create(@Valid @RequestBody ContractCreateReqVO createReqVO) {
        contractRoomService.createContractBill(createReqVO);
        return success();
    }

    @PostMapping("/create-renewal")
    @Operation(summary = "创建租客合同-续租")
//    @PreAuthorize("@ss.hasPermission('contract:createRenewal')")
    public CommonResult<Void> createRenewal(@Valid @RequestBody ContractRenewalReqVO createReqVO) {
        contractRoomService.createRenewalContractBill(createReqVO);
        return success();
    }

    @PostMapping("/create-exchange")
    @Operation(summary = "创建租客合同-换房")
//    @PreAuthorize("@ss.hasPermission('contract:createExchange')")
    public CommonResult<Void> createExchange(@Valid @RequestBody ContractExchangeReqVO createReqVO) {
        contractRoomService.createExchangeContractBill(createReqVO);
        return success();
    }

    @PostMapping("/create-refund")
    @Operation(summary = "创建租客合同-退租")
//    @PreAuthorize("@ss.hasPermission('contract:createExtension')")
    public CommonResult<Void> createRefund(@Validated @RequestBody ContractRefundReqVO reqVO) {
        reqVO.setOperator(SecurityFrameworkUtils.getLoginUser().getNickname());
        contractRoomService.createRefund(reqVO, Boolean.TRUE);
        return success();
    }


    @PostMapping("/update")
    @Operation(summary = "更新租客合同")
//    @PreAuthorize("@ss.hasPermission('contract:update')")
    public CommonResult<Boolean> update(@Valid @RequestBody ContractUpdateReqVO updateReqVO) {
        contractRoomService.update(updateReqVO);
        return success();
    }

    @PostMapping("/update-tenant-information")
    @Operation(summary = "更新租客基础信息")
//    @PreAuthorize("@ss.hasPermission('contract:update')")
    public CommonResult<Boolean> updateTenantInformation(@Valid @RequestBody ContractFoundationReqVO reqVO) {
        contractRoomService.updateTenantInformation(reqVO);
        return success();
    }

    @PostMapping("/update-Contract-information")
    @Operation(summary = "更新合同基础信息")
//    @PreAuthorize("@ss.hasPermission('contract:update')")
    public CommonResult<Boolean> updateContractInformation(@Valid @RequestBody ContractInformationReqVO reqVO) {
        contractRoomService.updateContractInformation(reqVO);
        return success();
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除租客合同")
    @Parameter(name = "id", description = "编号", required = true)
//    @PreAuthorize("@ss.hasPermission('contract:delete')")
    public CommonResult<Boolean> delete(@RequestParam("id") Long id) {
        contractRoomService.delete(id);
        return success();
    }

    @GetMapping("/get")
    @Operation(summary = "获得租客合同")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
//    @PreAuthorize("@ss.hasPermission('contract:query')")
    public CommonResult<ContractRespVO> get(@RequestParam("id") Long id) {
        ContractRoomDO contractRoomDO = contractRoomService.get(id);
        return success(ContractConvert.INSTANCE.convert(contractRoomDO));
    }

    @GetMapping("/list")
    @Operation(summary = "获得租客合同列表")
    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
//    @PreAuthorize("@ss.hasPermission('contract:query')")
    public CommonResult<List<ContractRespVO>> getList(@RequestParam("ids") Collection<Long> ids) {
        List<ContractRoomDO> list = contractRoomService.getList(ids);
        return success(ContractConvert.INSTANCE.convertList(list));
    }

    @GetMapping("/get-room-info")
    @Operation(summary = "根据房间id获取当前合同")
    @Parameter(name = "id", description = "房间id", required = true, example = "1024")
//    @PreAuthorize("@ss.hasPermission('contract:query')")
    public CommonResult<RoomContractRespVO> getRoomInfo(@RequestParam("id") Long id) {
        return success(contractRoomService.getRoomContract(id));
    }

    @GetMapping("/room-contract-list")
    @Operation(summary = "根据传参类型获取续租合同、历史合同、已经删除合同的对应的列表")
    @Parameter(name = "id", description = "房间id", required = true, example = "1024")
//    @PreAuthorize("@ss.hasPermission('contract:query')")
    public CommonResult<List<RoomContractListVO>> getRoomContractList(@RequestParam("id") Long id, @RequestParam("roomContractType") Integer roomContractType) {
        return success(contractRoomService.getRoomContractListByRoomContractType(id, roomContractType));
    }

    @GetMapping("/get-room-contract")
    @Operation(summary = "通过id获得房间合同")
    @Parameter(name = "id", description = "合同编号", required = true, example = "1024")
//    @PreAuthorize("@ss.hasPermission('contract:query')")
    public CommonResult<RoomContractRespVO> getRoomContract(@RequestParam("id") Long id) {
        return success(contractRoomService.getById(id));
    }

    /**
     * 企业合同小合同房间列表
     *
     * @param id 企业合同id
     * @return
     */
    @GetMapping("/get-rent-data")
    @Operation(summary = "企业合同小合同房间列表")
    @Parameter(name = "id", description = "企业合同id", required = true, example = "1024,2048")
//    @PreAuthorize("@ss.hasPermission('contract:query')")
    public CommonResult<List<ContractTenantInformationRepVO>> getByCompanyContract(@RequestParam("id") Long id) {
        return success(contractRoomService.getRentDataByContractId(id));
    }

    @PostMapping("/page")
    @Operation(summary = "租客合同分页查询")
//    @PreAuthorize("@ss.hasPermission('contract:create')")
    public CommonResult<ContractRoomListRespVO> pageCompanyContractSon(@Valid @RequestBody CompanyContractSonPageReqVO pageReqVO) {
        return success(contractRoomService.pageCompanyContractSon(pageReqVO));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出租客合同 Excel")
//    @PreAuthorize("@ss.hasPermission('contract:export')")
    public void exportContractExcel(@Valid CompanyContractSonPageReqVO exportReqVO,
                                    HttpServletResponse response) throws IOException {
        List<CompanySonsContractListExcelVO> contractList = contractRoomService.getContractList(exportReqVO);
        // 导出 Excel
        ExcelUtils.write(response, "租客合同.xls", "数据", CompanySonsContractListExcelVO.class, contractList);
    }

    /**
     * 退租结算单
     */
    @GetMapping("/contract-settlement")
    @Operation(summary = "退租生成结算单")
//    @PreAuthorize("@ss.hasPermission('contract:export')")
    public CommonResult<List<SettlementOrderFeeVO>> contractSettlement(@Valid ContractSettementVO contractSettementVO) {
        List<SettlementOrderFeeVO> settlement = contractSettlementService.settlement(contractSettementVO.getId(), contractSettementVO.getEndTime(), contractSettementVO.getSettlementType());
        return success(settlement);
    }

    @GetMapping("/contract-extension")
    @Operation(summary = "延期退租获取超期租金")
    public CommonResult<List<ContractExtensionVo>> contractExtension(@RequestParam("contractId") Long contractId) {
        List<ContractExtensionVo> contractExtensionVoList=new ArrayList<>();
        ContractExtensionVo contractExtensionVo=new ContractExtensionVo();
        //判断该合同是否延期
        ContractRoomDO contractRoomDO = contractRoomService.selectExtensionContract(contractId);
        if(null!=contractRoomDO){
            //获取延期天数
            long days = ChronoUnit.DAYS.between(contractRoomDO.getEndTime(), LocalDate.now());
            //获取合同延期配置
            ContractFixedFeeVo contractFiexdFee = contractFixedFeeService.getContractFiexdFee(contractRoomDO.getDeptId());
            if(null!=contractFiexdFee) {
                contractExtensionVo.setAmount(contractFiexdFee.getFixedFee());
                if(contractFiexdFee.getIsFixedFee()){
                    contractExtensionVo.setAmount((contractFiexdFee.getFixedFee().multiply(BigDecimal.valueOf(days))).setScale(2, BigDecimal.ROUND_HALF_UP));
                    contractExtensionVo.setRefundableAmount((contractFiexdFee.getFixedFee().multiply(BigDecimal.valueOf(days))).setScale(2, BigDecimal.ROUND_HALF_UP));
                    contractExtensionVo.setFeeName("超期租金");
                }else{
                    YearMonth yearMonth = YearMonth.now();
                    int daysInMonth = yearMonth.lengthOfMonth();
                    //计算日租金
                    BigDecimal divide = contractRoomDO.getMonthRent().divide(BigDecimal.valueOf(daysInMonth), 2, RoundingMode.HALF_UP);
                    contractExtensionVo.setAmount((divide.multiply(BigDecimal.valueOf(contractFiexdFee.getRoomRate())).multiply(BigDecimal.valueOf(days))).setScale(2, BigDecimal.ROUND_HALF_UP));
                    contractExtensionVo.setRefundableAmount((divide.multiply(BigDecimal.valueOf(contractFiexdFee.getRoomRate())).multiply(BigDecimal.valueOf(days))).setScale(2, BigDecimal.ROUND_HALF_UP));
                    contractExtensionVo.setFeeName("超期租金");
                }
                contractExtensionVoList.add(contractExtensionVo);
            }
        }
        return success(contractExtensionVoList);
    }

    @PostMapping("/delivery")
    @Operation(summary = "交房")
//    @PreAuthorize("@ss.hasPermission('contract:export')")
    public CommonResult<Void> delivery(@Valid @RequestBody ContractDeliveryReqVO req) {
        contractRoomService.delivery(req.getId());
        return success();
    }


    @GetMapping("/contract-count")
    @Operation(summary = "合同费统计")
//    @PreAuthorize("@ss.hasPermission('contract:export')")
    public CommonResult<RentOrderCountVO> contractCount(@Valid @RequestParam("id") Long id) {
        RentOrderCountVO rentOrderCountVO = contractRoomService.contractCount(id);
        return success(rentOrderCountVO);
    }

    /**
     * 个人客户-租赁信息
     *
     * @param req
     * @return
     */
    @GetMapping("/member-contract")
    public CommonResult<PageResult<MemberContractResp>> memberContract(@Valid MemberContractReq req) {
        return success(contractRoomService.memberContract(req));
    }

    /**
     * 工作台租客合同
     */
    @GetMapping("/get-contract")
    public CommonResult<RoomContractVO> getContract(@Valid HomeQueryVO req) {
        RoomContractVO contract = contractRoomService.getContract(req);
        return success(contract);
    }

    /**
    * 取消签约
    * */
    @GetMapping("/cancel-signing")
    public CommonResult<Void> cancelSigning(@Valid @RequestParam("id") Long id) {
        contractRoomService.cancelSigning(id);
        return success();
    }

    /**
     * 打开pdf
     * @param url
     * @param response
     * @throws UnsupportedEncodingException
     */
    @GetMapping("/openPdf")
    @PermitAll
    public void openPdf(@RequestParam("url")String url, HttpServletResponse response) throws UnsupportedEncodingException {
        HttpRequest request = HttpRequest.get(URLDecoder.decode(url, "UTF-8"));
        HttpResponse response1 = request.execute();
        response.setHeader("Content-Type", "application/pdf");//定义输出类型
        try(ServletOutputStream outputStream = response.getOutputStream()) {
            outputStream.write(response1.bodyBytes());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 判断分散式房源房间可录入合同
     */
    @PostMapping("/check-disperse-enter")
    public CommonResult<Boolean> checkDisperseRoomEnterContract(@Valid @RequestBody List<Long> roomIds) {
        return success(contractRoomService.checkDisperseRoomEnterContract(roomIds));
    }



    /**
     * 租赁合同变更管家
     */
    @PostMapping("/change-house-keep")
    public CommonResult<Boolean> changeHousekeep(@Valid @RequestBody ChangeHousekeepReqVO reqVO) {
        return success(contractRoomService.changeHousekeep(reqVO));
    }

    /**
     * 换组发起测试
     */
    @GetMapping("/change-room-approval")
    public CommonResult<Boolean> changeRoomApproval(@RequestParam("userId")Long userId,
                                                    @RequestParam("storeManager")Long storeManager,
                                                    @RequestParam("otherStoreManager")Long otherStoreManager,
                                                    @RequestParam("changeType")String changeType) {
        return success(contractRoomService.changeRoomApproval(userId,storeManager,otherStoreManager,changeType));
    }

    /**
     * 销售报表
     * @param vo
     * @return
     */
    @PostMapping("/salesStatement")
    public CommonResult<JSONObject> salesStatement(@RequestBody ContractSalesStatementVO vo){
        return contractRoomService.salesStatement(vo);
    }
}
